//启用低功耗蓝牙设备特征值变化时的 notify 功能
function notifyBLECharacteristicValueChange(deviceId, serviceId, uuid)
{
  wx.notifyBLECharacteristicValueChange({
    state: true, // 启用 notify 功能    
    deviceId: deviceId,
    serviceId: serviceId,
    characteristicId: uuid,
    success: function (res) {
      console.log('notifyBLECharacteristicValueChange success', res.errMsg);
    },
    fail: function (res) {
      console.log(res);
    }
  });      
}
//向低功耗蓝牙设备特征值中写入二进制数据
function writeBLECharacteristicValue(deviceId, serviceId, uuid, hex,callback)
{
  var typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {
    return parseInt(h, 16)
  }));
  var buffer = typedArray.buffer;

  wx.writeBLECharacteristicValue({
    deviceId: deviceId,
    serviceId: serviceId,
    characteristicId: uuid,
    value: buffer,
    success: function (res) {
      if (callback){
        callback();
      }
    },
    fail: function (err) {
      console.log(err);
    }
  });   
}

function checkBLEIsOpen(self,callback){
  wx.getBluetoothAdapterState({
    success: function (res) {
      if (!res.available) {
        showNotify(self,"设备无法开启蓝牙连接");
        wx.hideLoading();
      }else{
        if (!res.discovering) {
          callback(1);
        }else{
          callback(1);
        }        
      }
    }, fail: function (res) {
      callback(0);
    }
  });
}

function stopBluetoothDevicesDiscovery(){
  wx.stopBluetoothDevicesDiscovery({
    success: function (res) {
      console.log(res)
    }
  });
}
//监听蓝牙连接状态
function onBLEConnectionStateChange(self){
  wx.onBLEConnectionStateChange(function (res) {// 监听蓝牙连接
    if (!res.connected) {
      wx.removeStorageSync("deviceId");
      wx.removeStorageSync("deviceName");
      wx.removeStorageSync("boxStatus");
      var url = getCurrentPage();
      if (url == "pages/contesting/contesting" || url == "pages/contest/contest"
        || url == "pages/contestscore/contestscore") {          
        wx.redirectTo({
          url: '/pages/startBluetooth/startBlue?blebreak=1'
        });
      } else{
        showNotify(currentPage, "请注意，手机蓝牙与设备断开连接！");
      }
      
    }    
  });    
}
//1.开启蓝牙适配，并启用适配监听
function openBlueTooth(self,callback) { 
  wx.openBluetoothAdapter({
    success: function (res) {
      getBluetoothAdapterState(self,callback);
    }, fail: function (res) {
      showNotify(self, "蓝牙初始化失败，请先开启手机蓝牙");
    }
  });
  wx.onBluetoothAdapterStateChange(function (res) {
    var available = res.available;
    if (available) {
      getBluetoothAdapterState(self,callback);
    }
  })
}

//2.获取蓝牙适配器状态，判断设备蓝牙是否可用，可用则扫描蓝牙设备,获取已配对的蓝牙设备
function getBluetoothAdapterState(self,callback) { 
  wx.getBluetoothAdapterState({
    success: function (res) {
      var available = res.available, discovering = res.discovering;
      if (!available) {
        showNotify(self,'蓝牙初始化失败，请先开启手机蓝牙');
      } else {
        if (!discovering) {     
          searchDevices(callback);
        }
      }
    }
  })
}
//扫描设备
function searchDevices(callback){
  wx.getBluetoothDevices({
    success: function (res) { 
      let devices=res.devices;//已发现的设备
      if (!devices){
        devices=[];        
      }
      wx.startBluetoothDevicesDiscovery({
        services: [],
        allowDuplicatesKey: false,
        success: function (res) {
          if (res.isDiscovering) {
            let self = this;
            wx.onBluetoothDeviceFound(function (res) {
              if (res.devices.length>0){
                for(let i in res.devices){
                  devices.push(res.devices[i]);
                }                
                console.log(devices);
                callback(devices);
              }
            });
          }
          else{
            callback(devices);
          }
        },
        fail: function (err) {
          console.log(err);
          callback(devices);
        }
      });
    }
  });
}

//3.开始搜索蓝牙设备
function startBluetoothDevicesDiscovery() {
  wx.startBluetoothDevicesDiscovery({
    services: [],
    allowDuplicatesKey: false,
    success: function (res) {
      if (res.isDiscovering) {
        onBluetoothDeviceFound();
      }      
    },
    fail: function (err) {
      console.log(err);
    }
  });
}
//4.获取已配对的蓝牙设备
function getConnectedBluetoothDevices() {
  let serviceIds = wx.getStorageSync("serviceIds");
  if (serviceIds == null || serviceIds==""){
    serviceIds = [];
  }
  wx.getConnectedBluetoothDevices({
    services: serviceIds,
    success: function (res) {      
      return res['devices'];
    }
  });
}
//5.开启蓝牙搜索功能失败，则回到第2步重新检查蓝牙是适配器是否可用
function onBluetoothDeviceFound() {
  wx.onBluetoothDeviceFound(function (res) {
    if (res.devices.length>0){
      console.log("发现新设备，数量为" + res.devices.length);
    }else{
      console.log("未发现新设备");
    }
    return res.devices;
  });
}
//6.配对该设备,一旦开启连接则终止扫描附近蓝牙设备，终止读取本机已配对设备。
function startConnectDevices(self, deviceId, deviceName,callback) {
  wx.createBLEConnection({
    deviceId: deviceId,
    success: function (res) {
      if (res.errCode == 0) {
        wx.stopBluetoothDevicesDiscovery({
          success: function (res) {
            console.log(res)
          }
        });
        console.log("链接成功，正在匹配服务！");
        getService(self, deviceId, deviceName, callback);        
      }
    },
    fail: function (err) {
      console.log(err);
      wx.hideLoading();
      showNotify(self, '蓝牙连接失败');
    }
  });
}
//获取和设备对话的服务，经测试第一条服务是和设备对话的
function getService(self, deviceId, deviceName, callback) {
  onBLEConnectionStateChange(self);//监听蓝牙连接状态
  wx.getBLEDeviceServices({// 获取蓝牙设备service值
    deviceId: deviceId,
    success: function (res) {
      console.log("服务数量："+res.services.length);
      console.log(res.services);
      if (res.services.length > 0) {
        for (let i in res.services) {
          if (res.services[i].uuid == "0000FFE0-0000-1000-8000-00805F9B34FB") {
            getCharacter(deviceId, res.services[i].uuid, deviceName, callback);
            return false;
          }
        }
      }
    }
  })
}
//读取服务的特征值
function getCharacter(deviceId, serviceId, deviceName, callback) {
  wx.getBLEDeviceCharacteristics({
    deviceId: deviceId,
    serviceId: serviceId,
    success: function (res) {
      for (let i in res.characteristics) {
        let uuid = res.characteristics[i].uuid;
        if (i == 0) {
          wx.setStorageSync("serviceId", serviceId);
          wx.setStorageSync("uuid", uuid);
          //向设备发送配对密钥，系统默认为SNCode，此处上线时需改成动态的
          //let hexPwd = strToHexCharCode("@P#518629#@");
          wx.onBLECharacteristicValueChange(function (res) {
            let backresult = decodeUtf8(res.value); 
            if (backresult)
              backresult = backresult.toUpperCase();
            console.log("backresultold=" + backresult);
            if (/^#[0-9]+$/.test(backresult)) {             
              writeBLECharacteristicValue(deviceId, serviceId, uuid, "41434b234f4b23");//ACK#OK#
              if (callback) {
                wx.setStorageSync("statuses", backresult);
                callback(backresult);
              }
            } else if (backresult == "#ACKTION#"){
              wx.setStorageSync("boxStatus", "打擂中");
              
              let url = getCurrentPage();
              if (url == "pages/contestscore/contestscore" || url == "pages/contest/contest" 
              || url == "pages/startbluetooth/startblue"){
                wx.redirectTo({
                  url: '/pages/contesting/contesting'
                });
              }              
            }
          });
          let hexPwd = strToHexCharCode("@P#" + deviceName.toLowerCase().replace("redbuff#","")+"#@");
          writeBLECharacteristicValue(deviceId, serviceId, uuid, hexPwd);
          notifyBLECharacteristicValueChange(deviceId, serviceId, uuid);
        }
      }
    },
    fail: function (err) {
      console.log(err);
    }
  })
}

function getCurrentPage(){
  var pages = getCurrentPages()    //获取加载的页面
  var currentPage = pages[pages.length - 1]    //获取当前页面的对象    

  var url = currentPage.route.toLowerCase()    //当前页面url

  return url;
}

function decodeUtf8(arrayBuffer) {
  var result = "";
  var i = 0;
  var c = 0;
  var c1 = 0;
  var c2 = 0;

  var data = new Uint8Array(arrayBuffer);

  // If we have a BOM skip it
  if (data.length >= 3 && data[0] === 0xef && data[1] === 0xbb && data[2] === 0xbf) {
    i = 3;
  }

  while (i < data.length) {
    c = data[i];

    if (c < 128) {
      result += String.fromCharCode(c);
      i++;
    } else if (c > 191 && c < 224) {
      if (i + 1 >= data.length) {
        throw "UTF-8 Decode failed. Two byte character was truncated.";
      }
      c2 = data[i + 1];
      result += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
      i += 2;
    } else {
      if (i + 2 >= data.length) {
        throw "UTF-8 Decode failed. Multi byte character was truncated.";
      }
      c2 = data[i + 1];
      c3 = data[i + 2];
      result += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
      i += 3;
    }
  }
  return result.replace(/(^\s*)|(\s*$)/g, "");
}

function strToHexCharCode(str) {
  　　if (str === "")
    　　　　return "";
  　　var hexCharCode = [];
  　　hexCharCode.push("0x");
  　　for (var i = 0; i < str.length; i++) {
    　　　　hexCharCode.push((str.charCodeAt(i)).toString(16));
  　　}
  　　return hexCharCode.join("");
}

function showNotify(that, msg) {
  that.setData({ msgprop: msg });
  setTimeout(function () {
    that.setData({ msgprop: "" });
  }, 1500);
}
module.exports = {
  openBlueTooth: openBlueTooth,
  writeBLECharacteristicValue: writeBLECharacteristicValue,
  decodeUtf8: decodeUtf8,
  checkBLEIsOpen : checkBLEIsOpen,
  searchDevices: searchDevices,
  startConnectDevices: startConnectDevices,
  strToHexCharCode: strToHexCharCode
}